home *** CD-ROM | disk | FTP | other *** search
- Path: news.larc.nasa.gov!amiga-request
- From: amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator)
- Subject: v91i064: MP 1.0 - the MIDI Playground, Part01/02
- Reply-To: barrett@server.cs.jhu.edu
- Newsgroups: comp.sources.amiga
- Message-ID: <comp.sources.amiga:v91i064@ab20.larc.nasa.gov>
- Date: 15 Mar 91 19:25:16 GMT
- Approved: tadguy@uunet.UU.NET (Tad Guy)
- X-Mail-Submissions-To: amiga@uunet.uu.net
- X-Post-Discussions-To: comp.sys.amiga.misc
-
- Submitted-by: barrett@server.cs.jhu.edu
- Posting-number: Volume 91, Issue 064
- Archive-name: midi/mp-1.0/part01
-
- [ includes uuencoded executable ...tad ]
-
- This is a submission for comp.sources.amiga, entitled "MIDI
- Playground", written by me. It's a versatile utility for making your Amiga
- communicate with a MIDI instrument. It's helpful for learning about MIDI,
- designing MIDI software, and other related tasks.
-
- Uuencoded binary is included.
-
- Dan
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 2)."
- # Contents: CONTENTS Examples Examples.DOC Examples/CHORD-OFF
- # Examples/CHORD-ON Examples/DISPLAY-FUN README Scripts
- # Scripts/Converse Scripts/PatchChange Scripts/Text2Midi
- # Scripts/TwoWindows Source Source/Makefile Source/amigados.c
- # Source/cli.c Source/files.c Source/getopt.c Source/help.c
- # Source/iofunctions.c Source/main.c Source/midi.h Source/mp.h
- # Source/serial.c Source/text.c Source/version.h Source/wb.c
- # Wrapped by tadguy@ab20 on Fri Mar 15 14:25:13 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'CONTENTS' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'CONTENTS'\"
- else
- echo shar: Extracting \"'CONTENTS'\" \(353 characters\)
- sed "s/^X//" >'CONTENTS' <<'END_OF_FILE'
- XMIDI_Playground A small, useful utility for sending any MIDI data back and
- X forth between an Amiga and a MIDI instrument. Helpful for
- X learning about MIDI, writing/debugging MIDI software,
- X figuring out your instrument's system-exclusive
- X implementation, and more. Very versatile. Version 1.0,
- X includes source.
- X Author: Daniel J. Barrett
- X
- END_OF_FILE
- if test 353 -ne `wc -c <'CONTENTS'`; then
- echo shar: \"'CONTENTS'\" unpacked with wrong size!
- fi
- # end of 'CONTENTS'
- fi
- if test ! -d 'Examples' ; then
- echo shar: Creating directory \"'Examples'\"
- mkdir 'Examples'
- fi
- if test -f 'Examples.DOC' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Examples.DOC'\"
- else
- echo shar: Extracting \"'Examples.DOC'\" \(907 characters\)
- sed "s/^X//" >'Examples.DOC' <<'END_OF_FILE'
- XRead MP.DOC before you read this file.
- X
- XMP is very flexible because:
- X
- X o It can translate between 3 kinds of data formats:
- X
- X - Text.
- X - Binary data.
- X - MIDI data.
- X
- X o The input/output can be sent to/from:
- X
- X - Your CLI window.
- X - Files, using -g and -p.
- X - Files, using the CLI redirection symbols "<" and
- X ">".
- X - Newly-created windows, by specifying a file
- X name like "CON:0/0/640/100/MP Input".
- X - The MIDI port.
- X
- XMP does not have a window/mouse/icon graphic interface; instead, YOU
- Xdesign the interface using CLI scripts. See the "Scripts" directory
- Xfor some small examples. You can use MP in AREXX scripts too.
- X
- XFor a Workbench interface, use the IconX program (supplied with your
- XAmiga) to attach an icon to a CLI script. Then fill the CLI script
- Xwith MP commands.
- X
- XThe directory "Examples" has some sample files that use the input
- Xtext language. You can send them to your synthesizer.
- END_OF_FILE
- if test 907 -ne `wc -c <'Examples.DOC'`; then
- echo shar: \"'Examples.DOC'\" unpacked with wrong size!
- fi
- # end of 'Examples.DOC'
- fi
- if test -f 'Examples/CHORD-OFF' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Examples/CHORD-OFF'\"
- else
- echo shar: Extracting \"'Examples/CHORD-OFF'\" \(72 characters\)
- sed "s/^X//" >'Examples/CHORD-OFF' <<'END_OF_FILE'
- X; Cease playing a C major triad on MIDI channel 0.
- X
- X0x90 60 0 64 0 67 0
- END_OF_FILE
- if test 72 -ne `wc -c <'Examples/CHORD-OFF'`; then
- echo shar: \"'Examples/CHORD-OFF'\" unpacked with wrong size!
- fi
- # end of 'Examples/CHORD-OFF'
- fi
- if test -f 'Examples/CHORD-ON' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Examples/CHORD-ON'\"
- else
- echo shar: Extracting \"'Examples/CHORD-ON'\" \(69 characters\)
- sed "s/^X//" >'Examples/CHORD-ON' <<'END_OF_FILE'
- X; Play a C major triad on MIDI channel 0.
- X
- X0x90 60 127 64 127 67 127
- END_OF_FILE
- if test 69 -ne `wc -c <'Examples/CHORD-ON'`; then
- echo shar: \"'Examples/CHORD-ON'\" unpacked with wrong size!
- fi
- # end of 'Examples/CHORD-ON'
- fi
- if test -f 'Examples/DISPLAY-FUN' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Examples/DISPLAY-FUN'\"
- else
- echo shar: Extracting \"'Examples/DISPLAY-FUN'\" \(340 characters\)
- sed "s/^X//" >'Examples/DISPLAY-FUN' <<'END_OF_FILE'
- X; An example of sending text to the Matrix-12 display.
- X; Xpander users must change the 4th byte to 0x05.
- X; You MUST send exactly 80 characters or the Oberheim ignores you.
- X; Send this with:
- X; mp -g DISPLAY-FUN -it -om
- X
- X0xf0 0x10 0x02 0x06 0x01
- X"I THINK THAT I SHALL NEVER SEE "
- X"A POEM AS LOVELY AS LITTLE OL' ME "
- X0xf7
- END_OF_FILE
- if test 340 -ne `wc -c <'Examples/DISPLAY-FUN'`; then
- echo shar: \"'Examples/DISPLAY-FUN'\" unpacked with wrong size!
- fi
- # end of 'Examples/DISPLAY-FUN'
- fi
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(461 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- XMP: A MIDI Playground
- XAuthor: Daniel J. Barrett, barrett@cs.jhu.edu.
- XNo Copyright: 100% Public Domain.
- X Please share this program with others.
- X
- X MP is a small program that lets your Amiga communicate with a
- XMIDI instrument. It runs from the CLI only (but can be made to run
- Xfrom the Workbench by using "IconX").
- X
- XSee the file MP.DOC for full instructions on how to use this program.
- XSee EXAMPLES.DOC for information about the supplied examples and scripts.
- END_OF_FILE
- if test 461 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test ! -d 'Scripts' ; then
- echo shar: Creating directory \"'Scripts'\"
- mkdir 'Scripts'
- fi
- if test -f 'Scripts/Converse' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Scripts/Converse'\"
- else
- echo shar: Extracting \"'Scripts/Converse'\" \(151 characters\)
- sed "s/^X//" >'Scripts/Converse' <<'END_OF_FILE'
- Xrun <NIL: >NIL: mp -it -om -g "CON:0/1/640/75/Send MIDI; end with ^\"
- Xwait 1
- Xrun <NIL: >NIL: mp -im -ot -p "CON:0/76/640/75/Receive MIDI; end with ^C"
- END_OF_FILE
- if test 151 -ne `wc -c <'Scripts/Converse'`; then
- echo shar: \"'Scripts/Converse'\" unpacked with wrong size!
- fi
- # end of 'Scripts/Converse'
- fi
- if test -f 'Scripts/PatchChange' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Scripts/PatchChange'\"
- else
- echo shar: Extracting \"'Scripts/PatchChange'\" \(172 characters\)
- sed "s/^X//" >'Scripts/PatchChange' <<'END_OF_FILE'
- X.KEY patchnum/a
- X.BRA {
- X.KET }
- X
- Xecho "Changing to patch {patchnum} on MIDI channel 0..."
- Xecho > pipe:patchchange "0xC0 {patchnum}"
- Xmp -it -om -g pipe:patchchange
- Xecho Done!
- END_OF_FILE
- if test 172 -ne `wc -c <'Scripts/PatchChange'`; then
- echo shar: \"'Scripts/PatchChange'\" unpacked with wrong size!
- fi
- # end of 'Scripts/PatchChange'
- fi
- if test -f 'Scripts/Text2Midi' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Scripts/Text2Midi'\"
- else
- echo shar: Extracting \"'Scripts/Text2Midi'\" \(137 characters\)
- sed "s/^X//" >'Scripts/Text2Midi' <<'END_OF_FILE'
- X.KEY TextFile/a
- X.BRA {
- X.KET }
- X
- Xecho "Converting {TextFile} to {TextFile}.midi..."
- Xmp -it -ob -g {TextFile} -p {TextFile}.midi
- Xecho Done!
- END_OF_FILE
- if test 137 -ne `wc -c <'Scripts/Text2Midi'`; then
- echo shar: \"'Scripts/Text2Midi'\" unpacked with wrong size!
- fi
- # end of 'Scripts/Text2Midi'
- fi
- if test -f 'Scripts/TwoWindows' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Scripts/TwoWindows'\"
- else
- echo shar: Extracting \"'Scripts/TwoWindows'\" \(107 characters\)
- sed "s/^X//" >'Scripts/TwoWindows' <<'END_OF_FILE'
- Xmp -it -ot -g "CON:0/1/640/75/Type commands Here..." -p "CON:0/76/640/75/...and watch them come out here!"
- END_OF_FILE
- if test 107 -ne `wc -c <'Scripts/TwoWindows'`; then
- echo shar: \"'Scripts/TwoWindows'\" unpacked with wrong size!
- fi
- # end of 'Scripts/TwoWindows'
- fi
- if test ! -d 'Source' ; then
- echo shar: Creating directory \"'Source'\"
- mkdir 'Source'
- fi
- if test -f 'Source/Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Source/Makefile'\"
- else
- echo shar: Extracting \"'Source/Makefile'\" \(2707 characters\)
- sed "s/^X//" >'Source/Makefile' <<'END_OF_FILE'
- X###########################################################################
- X# Makefile: Makefile for Manx Aztec C, version 5.0.
- X# Part of MP, the MIDI Playground.
- X#
- X# Author: Daniel Barrett
- X# Version: See the file "version.h".
- X# Copyright: None! This program is in the Public Domain.
- X# Please share it with others.
- X###########################################################################
- X
- X
- XOPTIMIZE = -so
- XDEBUGGING = #-bs
- XLDEBUGGING = #-g
- X
- XLFLAGS = $(LDEBUGGING) +Q
- XCFLAGS = $(OPTIMIZE) -hi $(COMP_INC) $(DEBUGGING)
- XLIBS = -lc
- XCOMP_INC = headers.comp
- XLIBS = -lc
- X
- XBACKUPDIR = df1:sysex
- X
- X##############################################################################
- X# Files used for all programs.
- X##############################################################################
- X
- XPROG = mp
- XMAINHEADER = mp.h
- XHEADERS = $(MAINHEADER) version.h midi.h
- XSRC = text.c main.c serial.c getopt.c iofunctions.c help.c \
- X files.c wb.c cli.c amigados.c
- XOBJ = text.o main.o serial.o getopt.o iofunctions.o help.o \
- X files.o wb.o cli.o amigados.o
- X
- X##############################################################################
- X# The program.
- X##############################################################################
- X
- X$(PROG): $(COMP_INC) $(OBJ)
- X @echo ""
- X @echo "Ignore messages about _abort overriding library."
- X @echo ""
- X ln $(LFLAGS) $(OBJ) -o $(PROG) $(LIBS)
- X
- X$(OBJ): $(MAINHEADER)
- X
- X##############################################################################
- X# Individual dependencies.
- X##############################################################################
- X
- Xhelp.o: help.c $(MAINHEADER) version.h
- Xiofunctions.o: iofunctions.c $(MAINHEADER) midi.h
- Xserial.o: serial.c $(MAINHEADER) midi.h
- X
- X##############################################################################
- X# Compiled headers.
- X##############################################################################
- X
- X$(COMP_INC): $(MAINHEADER)
- X @echo "Compiling headers because of $?"
- X cc $(OPTIMIZE) $(DEBUGGING) -ho $(COMP_INC) $(MAINHEADER)
- X
- X#$(MAINHEADER): $(HEADERS)
- X
- X##############################################################################
- X# Clean up
- X##############################################################################
- X
- Xclean:
- X delete \#?.o \#?.pro
- X
- Xveryclean: clean
- X delete $(COMP_INC) $(PROG) \#?.dbg
- X
- Xcbackup:
- X copy \#?.c $(BACKUPDIR)
- X copy \#?.h $(BACKUPDIR)
- X copy Makefile $(BACKUPDIR)
- X
- Xbackup: cbackup
- X copy README $(BACKUPDIR)
- X copy \#?.DOC $(BACKUPDIR)
- X copy Scripts $(BACKUPDIR)/Scripts all
- X copy Examples $(BACKUPDIR)/Examples all
- X
- Xzoo: $(PROG)
- X delete ram:mp.zoo quiet
- X zoo a ram:mp.zoo Source/* Scripts/* Examples/* \
- X $(PROG) *.DOC README Makefile
- END_OF_FILE
- if test 2707 -ne `wc -c <'Source/Makefile'`; then
- echo shar: \"'Source/Makefile'\" unpacked with wrong size!
- fi
- # end of 'Source/Makefile'
- fi
- if test -f 'Source/amigados.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Source/amigados.c'\"
- else
- echo shar: Extracting \"'Source/amigados.c'\" \(1684 characters\)
- sed "s/^X//" >'Source/amigados.c' <<'END_OF_FILE'
- X/**************************************************************************
- X* amigados.c: Requestor and Environment Variable routines.
- X* Part of MP, the MIDI Playground.
- X*
- X* Author: Daniel Barrett
- X* Version: See the file "version.h".
- X* Copyright: None! This program is in the Public Domain.
- X* Please share it with others.
- X***************************************************************************/
- X
- X
- X#include <exec/types.h>
- X#include <stdlib.h>
- X#include <functions.h>
- X#include <libraries/dos.h>
- X#include <libraries/dosextens.h>
- X
- X
- Xvoid DisableRequestors(void);
- Xvoid EnableRequestors(void);
- X
- X
- X#define ENV_NAME_LENGTH BUFSIZ
- X
- X
- X/* Return the value of ENV: environment variable "variableName", if it
- X * exists. We use this instead of the built-in getenv() because we
- X * want to turn off requestors during the search for ENV:, in case it
- X * is not mounted. */
- X
- Xchar *GetEnv(char *variableName)
- X{
- X char *result;
- X
- X DisableRequestors(); /* In case ENV: is non-existent. */
- X result = getenv(variableName);
- X EnableRequestors();
- X return(result);
- X}
- X
- X
- X/***************************************************************************
- X* Deal with requestors.
- X***************************************************************************/
- X
- Xstatic APTR oldWindowPtr;
- Xstatic struct Process *theProc;
- X
- X/* Turn off system requestors for this process. */
- X
- Xvoid DisableRequestors(void)
- X{
- X theProc = (struct Process *)FindTask(NULL);
- X oldWindowPtr = theProc->pr_WindowPtr;
- X theProc->pr_WindowPtr = (APTR)(-1L);
- X}
- X
- X
- X/* Turn on system requestors for this process, after they have been
- X * turned off by DisableRequestors(), above. */
- X
- Xvoid EnableRequestors(void)
- X{
- X theProc->pr_WindowPtr = oldWindowPtr;
- X}
- END_OF_FILE
- if test 1684 -ne `wc -c <'Source/amigados.c'`; then
- echo shar: \"'Source/amigados.c'\" unpacked with wrong size!
- fi
- # end of 'Source/amigados.c'
- fi
- if test -f 'Source/cli.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Source/cli.c'\"
- else
- echo shar: Extracting \"'Source/cli.c'\" \(2379 characters\)
- sed "s/^X//" >'Source/cli.c' <<'END_OF_FILE'
- X/**************************************************************************
- X* cli.c: The command-line interface for MP.
- X* Part of MP, the MIDI Playground.
- X*
- X* Author: Daniel Barrett
- X* Version: See the file "version.h".
- X* Copyright: None! This program is in the Public Domain.
- X* Please share it with others.
- X***************************************************************************/
- X
- X
- X#include "mp.h"
- X
- X
- X/* The main program from the CLI. Check the command-line arguments, set
- X * up the input and output files, and call MIDIPlayground(). */
- X
- XBOOL CommandLineProgram(int argc, char *argv[])
- X{
- X FILE *in, *out;
- X char *infile, *outfile;
- X FLAGS theFlags[NUM_FLAGS];
- X
- X InitStuff(theFlags, &in, &out, &infile, &outfile);
- X
- X if ((argc == 1) || (argc == 2 && !strcmp(argv[1], "?")))
- X Help(argv[0]);
- X else if (!HandleOptions(argc, argv, theFlags, &infile, &outfile))
- X {
- X fprintf(stderr, "There is an error in your options/flags.\n");
- X BegForUsage(argv[0]);
- X }
- X else if (!SetupFiles(infile, outfile, &in, &out))
- X ;
- X else if (optind < argc)
- X {
- X fprintf(stderr, "You gave me too many arguments.\n");
- X BegForUsage(argv[0]);
- X }
- X else
- X (void)MIDIPlayground(theFlags, in, out);
- X
- X CloseFiles(in, out, infile, outfile);
- X}
- X
- X
- X/************************************************************************
- X* Handling command-line options.
- X************************************************************************/
- X
- XBOOL HandleOptions(int argc, char *argv[], FLAGS theFlags[], char **infile,
- X char **outfile)
- X{
- X int c;
- X BOOL success = TRUE;
- X static char options[] = GETOPT_OPTIONS;
- X
- X while ((c = getopt(argc, argv, options)) != EOF)
- X {
- X switch (c)
- X {
- X case OPT_INPUT:
- X success &= !theFlags[FLAG_ITYPE];
- X success &= CheckIOType(*optarg, FLAG_ITYPE, theFlags);
- X break;
- X case OPT_OUTPUT:
- X success &= !theFlags[FLAG_OTYPE];
- X success &= CheckIOType(*optarg, FLAG_OTYPE, theFlags);
- X break;
- X case OPT_INFILE:
- X success &= (optarg[0] != '\0');
- X success &= MakeFilename(infile, optarg);
- X break;
- X case OPT_OUTFILE:
- X success &= (optarg[0] != '\0');
- X success &= MakeFilename(outfile, optarg);
- X break;
- X case OPT_SYSEX:
- X success &= !theFlags[FLAG_SYSEX];
- X theFlags[FLAG_SYSEX]++;
- X break;
- X default:
- X success = FALSE;
- X break;
- X }
- X }
- X return(success && CheckFlags(theFlags));
- X}
- X
- X
- END_OF_FILE
- if test 2379 -ne `wc -c <'Source/cli.c'`; then
- echo shar: \"'Source/cli.c'\" unpacked with wrong size!
- fi
- # end of 'Source/cli.c'
- fi
- if test -f 'Source/files.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Source/files.c'\"
- else
- echo shar: Extracting \"'Source/files.c'\" \(3363 characters\)
- sed "s/^X//" >'Source/files.c' <<'END_OF_FILE'
- X/**************************************************************************
- X* files.c: File open/close, input/output, etc.
- X* Part of MP, the MIDI Playground.
- X*
- X* Author: Daniel Barrett
- X* Version: See the file "version.h".
- X* Copyright: None! This program is in the Public Domain.
- X* Please share it with others.
- X***************************************************************************/
- X
- X
- X#include <stdio.h>
- X#include <exec/types.h>
- X#include <libraries/dos.h>
- X#include <libraries/dosextens.h>
- X
- X
- X/* Open a file and return a pointer to it. */
- X
- XFILE *OpenAFile(char *filename, char *mode, char *readOrWrite)
- X{
- X FILE *fp;
- X
- X if ((fp = fopen(filename, mode)) == NULL)
- X fprintf(stderr, "Cannot %s the file \"%s\",\n",
- X readOrWrite, filename);
- X return(fp);
- X}
- X
- X
- X/* Open a file for reading. We might also have a macro with the same name,
- X * so we used ifdef's. */
- X
- X#ifndef OpenReadFile
- XFILE *OpenReadFile(char *filename)
- X{
- X return(OpenAFile(filename, "r", "read"));
- X}
- X#endif
- X
- X
- X/* Open a file for writing. We might also have a macro with the same name,
- X * so we used ifdef's. */
- X
- X#ifndef OpenWriteFile
- XFILE *OpenWriteFile(char *filename)
- X{
- X return(OpenAFile(filename, "w", "write"));
- X}
- X#endif
- X
- X
- X/* Tell me whether or not a file exists. */
- X
- XBOOL FileExists(char *filename)
- X{
- X BPTR lock;
- X
- X if ((lock = Lock(filename, ACCESS_READ)) != NULL)
- X {
- X UnLock(lock);
- X return(TRUE);
- X }
- X return(FALSE);
- X}
- X
- X
- X/* See if we want to overwrite an existing file. */
- X
- X/* BUFSIZ is too large, perhaps -- change later -- but don't compromise
- X * on correct reading of the user's input. Too small, and extra unread
- X * chars are read on the NEXT call (yuck). If you use gets(), too much
- X * input crashes the program. */
- X
- XBOOL DontOverwriteExistingFile(char *filename)
- X{
- X char buf[BUFSIZ];
- X BOOL safety = TRUE;
- X
- X if (FileExists(filename))
- X {
- X fprintf(stderr,
- X "File \"%s\" already exists.\nOVERWRITE it? [%s]: ",
- X filename, "Yes/No, RETURN=No");
- X fflush(stderr);
- X
- X if (fgets(buf, BUFSIZ-1, stdin))
- X safety = (toupper(buf[0]) != 'Y');
- X else
- X safety = TRUE;
- X }
- X else
- X safety = FALSE; /* File doesn't exist. */
- X
- X if (safety)
- X fprintf(stderr, "%s not overwritten.\n\n", filename);
- X
- X return(safety);
- X}
- X
- X
- X/* Open the input and output files.
- X * We open input AFTER output in case the user has specified CON: windows,
- X * so the input window is the active one. */
- X
- XBOOL SetupFiles(char *infile, char *outfile, FILE **in, FILE **out)
- X{
- X if (!outfile || (outfile[0] == '\0'))
- X *out = stdout;
- X else if (DontOverwriteExistingFile(outfile))
- X return(FALSE);
- X else if ((*out = OpenWriteFile(outfile)) == NULL)
- X return(FALSE);
- X
- X if (!infile || (infile[0] == '\0'))
- X *in = stdin;
- X else if ((*in = OpenReadFile(infile)) == NULL)
- X return(FALSE);
- X
- X return(TRUE);
- X}
- X
- X
- X/* Close the files used by the program, and deallocate the arrays used
- X * for storing the filenames. */
- X
- Xvoid CloseFiles(FILE *in, FILE *out, char *filein, char *fileout)
- X{
- X if (in && (in != stdin)) fclose(in);
- X if (out && (out != stdout)) fclose(out);
- X if (filein) free(filein);
- X if (fileout) free(fileout);
- X}
- X
- X
- X/* Allocate space to store a filename, and copy the contents of "src" into
- X * it. */
- X
- XBOOL MakeFilename(char **dest, char *src)
- X{
- X if ((!src) || (*src == '\0')
- X || ((*dest = (char *)malloc(strlen(src)+1)) == NULL))
- X return(FALSE);
- X else
- X {
- X strcpy(*dest, src);
- X return(TRUE);
- X }
- X}
- END_OF_FILE
- if test 3363 -ne `wc -c <'Source/files.c'`; then
- echo shar: \"'Source/files.c'\" unpacked with wrong size!
- fi
- # end of 'Source/files.c'
- fi
- if test -f 'Source/getopt.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Source/getopt.c'\"
- else
- echo shar: Extracting \"'Source/getopt.c'\" \(7295 characters\)
- sed "s/^X//" >'Source/getopt.c' <<'END_OF_FILE'
- X/****************************************************************************
- X * getopt(): Return the next user option on each iteration.
- X * This is a clone of the usual UNIX getopt() function.
- X * If you have never used a getopt() before, you'll have to
- X * read about it on any UNIX machine or other C system that
- X * documents it.
- X *
- X * Author: Daniel Barrett, barrett@cs.jhu.edu.
- X * Date: February 20, 1991.
- X * Version: 1.1.
- X *
- X * License: This code is placed in the Public Domain.
- X * Give it away to anybody for free!
- X * Use it for any purpose you like!
- X *
- X * If you use this code in a program, please give me credit
- X * for my work. Thanks!
- X *
- X * Why I wrote it:
- X *
- X * Because every other getopt() function I have ever seen
- X * had source code that was difficult to understand.
- X * I wrote this code to be very modular and readable.
- X * I hope you find it instructive and/or helpful.
- X *
- X * REVISION HISTORY:
- X * Version: 1.1
- X * Date: February 20, 1991.
- X * Comments: Bug fix in Pass(). Forgot to check that the
- X * current argument is non-empty and starts with
- X * a DASH.
- X *
- X * Got rid of the unnecessary "g_" at the beginning
- X * of each function name. Since they're static, we
- X * don't have to worry about duplication of names
- X * by the calling program.
- X *
- X * Version: 1.0
- X * Date: April 12, 1990.
- X * Comments: First released version.
- X *
- X ****************************************************************************/
- X
- X#ifndef __STDIO_H /* If we haven't already included stdio.h, do it. */
- X#include <stdio.h> /* Maybe someday I'll eliminate this. */
- X#endif
- X
- X/************************************************************************
- X* Some constants.
- X************************************************************************/
- X
- X#define DASH '-' /* This preceeds an option. */
- X#define ARG_COMING ':' /* In the option string, this indicates that
- X * that the option requires an argument. */
- X#define UNKNOWN_OPT '?' /* The char returned for unknown option. */
- X
- X/************************************************************************
- X* Internal error codes.
- X************************************************************************/
- X
- X#define ERROR_BAD_OPTION 1
- X#define ERROR_MISSING_ARGUMENT 2
- X
- X/************************************************************************
- X* Mnemonic macros.
- X************************************************************************/
- X
- X
- X
- X/************************************************************************
- X* ANSI function prototypes.
- X************************************************************************/
- X
- Xint getopt(int argc, char *argv[], char *optString);
- Xstatic int NextOption(char *argv[], char *optString);
- Xstatic int RealOption(char *argv[], char *str, int *skip, int *ind,
- X int opt);
- Xstatic void HandleArgument(char *argv[], int *optind, int *skip);
- Xstatic void Error(int err, int c);
- Xstatic void Pass(char *argv[], int *optind, int *optsSkipped);
- X
- Xextern char *index();
- X
- X/************************************************************************
- X* Global variables. You must declare these externs in your program
- X* if you want to see their values!
- X************************************************************************/
- X
- Xchar *optarg = NULL; /* This will point to a required argument, if any. */
- Xint optind = 1; /* The index of the next argument in argv. */
- Xint opterr = 1; /* 1 == print internal error messages. 0 else. */
- Xint optopt; /* The actual option letter that was found. */
- X
- X
- Xint getopt(int argc, char *argv[], char *optString)
- X{
- X optarg = NULL;
- X if (optind < argc) /* More arguments to check. */
- X return(NextOption(argv, optString));
- X else /* We're done. */
- X return(EOF);
- X}
- X
- X
- X/* If the current argument does not begin with DASH, it is not an option.
- X * Return EOF.
- X * If we have ONLY a DASH, and nothing after it... return EOF as well.
- X * If we have a DASH followed immediately by another DASH, this is the
- X * special "--" option that means "no more options follow." Return EOF.
- X * Otherwise, we have an actual option or list of options. Process it. */
- X
- Xstatic int NextOption(char *argv[], char *optString)
- X{
- X static int optsSkipped = 0; /* In a single argv[i]. */
- X
- X if ((argv[optind][0] == DASH)
- X && ((optopt = argv[optind][1+optsSkipped]) != '\0'))
- X {
- X if (optopt == DASH)
- X {
- X optind++;
- X return(EOF);
- X }
- X else
- X return(RealOption(argv, optString, &optsSkipped,
- X &optind, optopt));
- X }
- X else
- X return(EOF);
- X}
- X
- X
- X/* At this point, we know that argv[optind] is an option or list of
- X * options. If this is a list of options, *optsSkipped tells us how
- X * many of those options have ALREADY been parsed on previous calls
- X * to getopt().
- X * If the option is not legal (not in optString), complain and return
- X * UNKNOWN_OPT.
- X * If the option requires no argument, just return the option letter.
- X * If the option requires an argument, call HandleArgument and return
- X * the option letter. */
- X
- Xstatic int RealOption(char *argv[], char *optString, int *optsSkipped,
- X int *optind, int optopt)
- X{
- X char *where;
- X
- X (*optsSkipped)++;
- X if (where = index(optString, optopt))
- X {
- X if (*(where+1) == ARG_COMING)
- X HandleArgument(argv, optind, optsSkipped);
- X
- X Pass(argv, optind, optsSkipped);
- X return(optopt);
- X }
- X else
- X {
- X Error(ERROR_BAD_OPTION, optopt);
- X Pass(argv, optind, optsSkipped);
- X return(UNKNOWN_OPT);
- X }
- X}
- X
- X
- X/* We have an option in argv[optind] that requires an argument. If there
- X * is no whitespace after the option letter itself, take the rest of
- X * argv[optind] to be the argument.
- X * If there IS whitespace after the option letter, take argv[optind+1] to
- X * be the argument.
- X * Otherwise, if there is NO argument, complain! */
- X
- Xstatic void HandleArgument(char *argv[], int *optind, int *optsSkipped)
- X{
- X if (argv[*optind][1+(*optsSkipped)])
- X optarg = argv[*optind] + 1 + (*optsSkipped);
- X else if (argv[(*optind)+1])
- X {
- X optarg = argv[(*optind)+1];
- X (*optind)++;
- X }
- X else
- X Error(ERROR_MISSING_ARGUMENT, optopt);
- X
- X (*optsSkipped) = 0;
- X (*optind)++;
- X}
- X
- X
- X/* Print an appropriate error message. */
- X
- Xstatic void Error(int err, int c)
- X{
- X static char *optmsg = "Illegal option.\n";
- X static char *argmsg = "An argument is required, but missing.\n";
- X
- X if (opterr)
- X {
- X if (err == ERROR_BAD_OPTION)
- X fprintf(stderr, "-%c: %s", c, optmsg);
- X else if (err == ERROR_MISSING_ARGUMENT)
- X fprintf(stderr, "-%c: %s", c, argmsg);
- X
- X else /* Sanity check! */
- X fprintf(stderr, "-%c: an unknown error occurred\n",
- X c);
- X }
- X}
- X
- X
- X/* We have reached the end of argv[optind]... there are no more options
- X * in it to parse. Skip to the next item in argv. */
- X
- Xstatic void Pass(char *argv[], int *optind, int *optsSkipped)
- X{
- X if (argv[*optind]
- X && (argv[*optind][0] == DASH)
- X && (argv[*optind][1+(*optsSkipped)] == NULL))
- X {
- X (*optind)++;
- X (*optsSkipped) = 0;
- X }
- X}
- X
- X/***************************************************************************
- X* A test program. Compile this file with -DTESTME as an option.
- X***************************************************************************/
- X
- X#ifdef TESTME
- Xmain(int argc, char *argv[])
- X{
- X char c;
- X
- X while ((c = getopt(argc, argv, "a:b:cde")) != EOF)
- X {
- X printf("OPTION %c", c);
- X if ((c == 'a') || (c == 'b'))
- X printf(", %s\n", optarg);
- X else
- X printf("\n");
- X printf("argc=%d, optind=%d\n", argc, optind);
- X }
- X exit(0);
- X}
- X#endif
- END_OF_FILE
- if test 7295 -ne `wc -c <'Source/getopt.c'`; then
- echo shar: \"'Source/getopt.c'\" unpacked with wrong size!
- fi
- # end of 'Source/getopt.c'
- fi
- if test -f 'Source/help.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Source/help.c'\"
- else
- echo shar: Extracting \"'Source/help.c'\" \(2340 characters\)
- sed "s/^X//" >'Source/help.c' <<'END_OF_FILE'
- X/**************************************************************************
- X* help.c: Functions for giving help to the user.
- X* Part of MP, the MIDI Playground.
- X*
- X* Author: Daniel Barrett
- X* Version: See the file "version.h".
- X* Copyright: None! This program is in the Public Domain.
- X* Please share it with others.
- X***************************************************************************/
- X
- X
- X#include "mp.h"
- X#include "version.h"
- X
- X
- X/* Print a detailed help message. */
- X
- Xvoid Help(char *progName)
- X{
- X FILE *fp = stderr;
- X
- X fprintf(fp, "MIDI Playground (%s), version %s, by Daniel Barrett."
- X " 100%% Public Domain!\n",
- X progName, VERSION);
- X fprintf(fp,
- X "Usage: %s -%c<FORMAT> -%c<FORMAT> [-%c infile] [-%c outfile]\n",
- X progName,
- X OPT_INPUT, OPT_OUTPUT, OPT_INFILE, OPT_OUTFILE);
- X
- X fprintf(fp,
- X "The program quits at end-of-file, or when ^C is pressed.\n");
- X
- X fprintf(fp, "\nThe flags may appear in any order:\n");
- X fprintf(fp, "\t-%c\tSpecify the input format. [MANDATORY]\n",
- X OPT_INPUT);
- X fprintf(fp, "\t-%c\tSpecify the output format. [MANDATORY]\n",
- X OPT_OUTPUT);
- X fprintf(fp, "\t\t\"-%c\" and \"-%c\" must EACH be followed by",
- X OPT_INPUT, OPT_OUTPUT);
- X fprintf(fp, " exactly one of:\n");
- X fprintf(fp, "\t\t\t%c\tText (readable by humans).\n", OPT_TEXT);
- X fprintf(fp, "\t\t\t%c\tBinary data (for files).\n", OPT_BINARY);
- X fprintf(fp, "\t\t\t%c\tMIDI (using MIDI port).\n", OPT_MIDI);
- X fprintf(fp, "\t-%c\tGet data from this file. [Default=keyboard]\n",
- X OPT_INFILE);
- X fprintf(fp, "\t-%c\tPut data into this file. [Default=screen]\n",
- X OPT_OUTFILE);
- X
- X fprintf(fp, "\nExamples:\n");
- X fprintf(fp, "\t%s -%c%c -%c%c -%c data\t%s\n",
- X progName,
- X OPT_INPUT, OPT_MIDI, OPT_OUTPUT, OPT_BINARY,
- X OPT_OUTFILE,
- X "Read MIDI & put it into binary file \"data\".");
- X fprintf(fp,
- X "\t%s -%c%c -%c%c\t\tRead typed text, send to MIDI (fun!).\n",
- X progName,
- X OPT_INPUT, OPT_TEXT, OPT_OUTPUT, OPT_MIDI);
- X
- X fprintf(fp, "\n\"%s -%c%c\" understands decimal, octal, hex,",
- X progName, OPT_INPUT, OPT_TEXT);
- X fprintf(fp, " binary, characters, and strings.\n");
- X fprintf(fp, "For details, type %c while in \"-%c%c\" mode.\n",
- X HELP_SYMBOL, OPT_INPUT, OPT_TEXT);
- X}
- X
- X
- X/* Tell the user how to get more help. */
- X
- Xvoid BegForUsage(char *progName)
- X{
- X fprintf(stderr, "Please type \"%s ?\" for instructions.\n",
- X progName);
- X}
- END_OF_FILE
- if test 2340 -ne `wc -c <'Source/help.c'`; then
- echo shar: \"'Source/help.c'\" unpacked with wrong size!
- fi
- # end of 'Source/help.c'
- fi
- if test -f 'Source/iofunctions.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Source/iofunctions.c'\"
- else
- echo shar: Extracting \"'Source/iofunctions.c'\" \(3430 characters\)
- sed "s/^X//" >'Source/iofunctions.c' <<'END_OF_FILE'
- X/**************************************************************************
- X* iofunctions.c:
- X* Functions for input/output in a variety of formats.
- X* Part of MP, the MIDI Playground.
- X*
- X* Author: Daniel Barrett
- X* Version: See the file "version.h".
- X* Copyright: None! This program is in the Public Domain.
- X* Please share it with others.
- X***************************************************************************/
- X
- X
- X#include "mp.h"
- X#include "midi.h"
- X
- X
- X/* Read data from MIDI. Return the value of the next MIDI byte. Because
- X * reading byte-by-byte from the MIDI port is inefficient, we read as
- X * much as we can and keep it in a static buffer. */
- X
- XMIDI_RESULT FromMidi(FILE *in, MIDI_VALUE *value)
- X{
- X static long bytesWaiting = 0L; /* # bytes waiting at serial port. */
- X static UBYTE buf[BUFSIZ]; /* Static buffer. */
- X static long currentByte = 0L; /* Index of next byte to return. */
- X
- X if (currentByte >= bytesWaiting)
- X {
- X bytesWaiting = FastSerialRead(buf);
- X currentByte = 0L;
- X }
- X
- X if (bytesWaiting == CTRL_C_NO_BYTES)
- X {
- X bytesWaiting = currentByte = 0L;
- X return(RESULT_STOP);
- X }
- X else if (bytesWaiting <= 0)
- X {
- X bytesWaiting = currentByte = 0L;
- X return(RESULT_ERROR);
- X }
- X else
- X {
- X *value = buf[currentByte++];
- X return(RESULT_OK);
- X }
- X}
- X
- X
- X/* Write a byte to MIDI. It is inefficient to write 1 byte at a time, but
- X * we want instant transmission. I will rewrite this eventually. */
- X
- XBOOL ToMidi(FILE *dummy, MIDI_VALUE value)
- X{
- X PrepareToWriteMidi(&value, 1);
- X return(DoTheIO() == 1L);
- X}
- X
- X/* Read 1 byte from text. We use a finite state automaton.
- X * If an error occurs, assign the value of the last character read
- X * to *answer. */
- X
- XMIDI_RESULT FromText(FILE *in, MIDI_VALUE *value)
- X{
- X STATE_T state = STATE_NORMAL;
- X int c;
- X
- X *value = 0L;
- X
- X while ((state != STATE_SUCCESS) && (state != STATE_ERROR)
- X && (state != STATE_OVERFLOW)
- X && ((c = getc(in)) != EOF))
- X
- X state = NewState(c, state, value);
- X
- X if (state == STATE_SUCCESS)
- X return(RESULT_OK);
- X else if (c == EOF && state == STATE_NORMAL)
- X return(RESULT_STOP);
- X else if (c == EOF)
- X return(RESULT_ERROR);
- X else if (state == STATE_OVERFLOW)
- X return(RESULT_OVERFLOW);
- X else
- X {
- X *value = c;
- X return(RESULT_ERROR);
- X }
- X}
- X
- X
- X/* Write 1 MIDI value as text. */
- X
- XBOOL ToText(FILE *out, MIDI_VALUE value)
- X{
- X static long byt = 0L;
- X
- X fprintf(out, "<%6ld> ", ++byt);
- X PrintNumber(value, out);
- X}
- X
- X
- X/* Read 1 MIDI value from a binary file. Inefficient. */
- X
- XMIDI_RESULT FromBinary(FILE *in, MIDI_VALUE *value)
- X{
- X int c;
- X if ((c = getc(in)) != EOF)
- X {
- X *value = (MIDI_VALUE)c;
- X return(RESULT_OK);
- X }
- X
- X return(RESULT_STOP);
- X}
- X
- X
- X/* Write 1 MIDI value to a binary file. Inefficient. */
- X
- XBOOL ToBinary(FILE *out, MIDI_VALUE value)
- X{
- X return(putc(value, out) != EOF);
- X}
- X
- X
- X/****************************************************************************
- X* Skipping input.
- X****************************************************************************/
- X
- X
- X/* Skip to the next valid text input. */
- X
- Xvoid SkipText(FILE *in, MIDI_VALUE value)
- X{
- X register int c;
- X
- X if (isspace(value))
- X return;
- X
- X while ((c = getc(in)) != EOF && !isspace(c))
- X ;
- X if (c != EOF)
- X ungetc(c, in);
- X}
- X
- X
- X/* Skip to the next valid MIDI input by clearing the serial port buffer. */
- X
- Xvoid SkipMidi(FILE *dummy, MIDI_VALUE junk)
- X{
- X ResetSerialPort();
- X}
- X
- X
- X/* Skip to the next valid binary value. This is currently just a stub. */
- X
- Xvoid SkipBinary(FILE *in, MIDI_VALUE junk)
- X{
- X return;
- X}
- END_OF_FILE
- if test 3430 -ne `wc -c <'Source/iofunctions.c'`; then
- echo shar: \"'Source/iofunctions.c'\" unpacked with wrong size!
- fi
- # end of 'Source/iofunctions.c'
- fi
- if test -f 'Source/main.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Source/main.c'\"
- else
- echo shar: Extracting \"'Source/main.c'\" \(4433 characters\)
- sed "s/^X//" >'Source/main.c' <<'END_OF_FILE'
- X/**************************************************************************
- X* main.c: The main program and supporting stuff.
- X* Part of MP, the MIDI Playground.
- X*
- X* Author: Daniel Barrett
- X* Version: See the file "version.h".
- X* Copyright: None! This program is in the Public Domain.
- X* Please share it with others.
- X***************************************************************************/
- X
- X
- X#include "mp.h"
- X
- XBOOL WorkbenchProgram(char *argv[]);
- XBOOL CommandLineProgram(int argc, char *argv[]);
- X
- Xmain(int argc, char *argv[])
- X{
- X BOOL success;
- X
- X if (argc == 0)
- X success = WorkbenchProgram(argv);
- X else
- X success = CommandLineProgram(argc, argv);
- X
- X exit(success ? RETURN_OK : RETURN_FAIL);
- X}
- X
- X
- X/************************************************************************
- X* Initialization of important variables.
- X************************************************************************/
- X
- Xvoid InitStuff(FLAGS theFlags[], FILE **in, FILE **out, char **inFile,
- X char **outFile)
- X{
- X int i;
- X
- X for (i=0; i<NUM_FLAGS; i++) /* Flags. */
- X theFlags[i] = (FLAGS)0;
- X
- X *in = stdin; /* Input file. */
- X *out = stdout; /* Output file. */
- X *inFile = NULL; /* Input file name. */
- X *outFile = NULL; /* Output file name. */
- X}
- X
- X
- X/************************************************************************
- X* Open the serial port if necessary, and have fun!
- X************************************************************************/
- X
- XBOOL MIDIPlayground(FLAGS theFlags[], FILE *in, FILE *out)
- X{
- X if ((theFlags[FLAG_ITYPE] == OPT_MIDI)
- X || (theFlags[FLAG_OTYPE] == OPT_MIDI))
- X {
- X if (!SerialSetup(theFlags[FLAG_SYSEX]))
- X return(FALSE);
- X ResetSerialPort();
- X }
- X
- X ReadAndWriteStuff(theFlags, in, out);
- X
- X
- X if ((theFlags[FLAG_ITYPE] == OPT_MIDI)
- X || (theFlags[FLAG_OTYPE] == OPT_MIDI))
- X SerialShutdown();
- X
- X return(TRUE); /* Stub. */
- X}
- X
- X
- X/************************************************************************
- X* Use the appropriate I/O functions until we're done.
- X************************************************************************/
- X
- Xvoid ReadAndWriteStuff(FLAGS theFlags[], FILE *in, FILE *out)
- X{
- X MIDI_RESULT result;
- X MIDI_VALUE value;
- X MIDI_RESULT (*getfcn)(FILE *f, MIDI_VALUE *value);
- X BOOL (*putfcn)(FILE *f, MIDI_VALUE value);
- X void (*skipfcn)(FILE *f, MIDI_VALUE value);
- X
- X SetTheFunctions(&getfcn, &putfcn, &skipfcn, theFlags);
- X
- X while ((result = getfcn(in, &value)) != RESULT_STOP)
- X {
- X switch (result)
- X {
- X case RESULT_OK:
- X putfcn(out, value);
- X break;
- X case RESULT_ERROR:
- X fprintf(out, "ERROR\n");
- X skipfcn(in, value);
- X break;
- X case RESULT_OVERFLOW:
- X fprintf(out, "VALUE TOO BIG (overflow)\n");
- X skipfcn(in, value);
- X break;
- X default:
- X skipfcn(in, value);
- X fprintf(out, "An unknown error occurred.\n");
- X break;
- X }
- X }
- X}
- X
- X
- X/************************************************************************
- X* Choose the appropriate I/O functions.
- X************************************************************************/
- X
- Xvoid SetTheFunctions(MIDI_RESULT (**getfcn)(), BOOL (**putfcn)(),
- X void (**skipfcn)(), FLAGS theFlags[])
- X{
- X switch (theFlags[FLAG_ITYPE])
- X {
- X case OPT_TEXT:
- X *getfcn = FromText;
- X *skipfcn = SkipText;
- X break;
- X case OPT_BINARY:
- X *getfcn = FromBinary;
- X *skipfcn = SkipBinary;
- X break;
- X case OPT_MIDI:
- X *getfcn = FromMidi;
- X *skipfcn = SkipMidi;
- X break;
- X default:
- X *getfcn = FromText; /* Least dangerous fcn. */
- X *skipfcn = SkipText; /* Least dangerous fcn. */
- X }
- X
- X switch (theFlags[FLAG_OTYPE])
- X {
- X case OPT_TEXT:
- X *putfcn = ToText;
- X break;
- X case OPT_BINARY:
- X *putfcn = ToBinary;
- X break;
- X case OPT_MIDI:
- X *putfcn = ToMidi;
- X break;
- X default:
- X *putfcn = ToText; /* Least dangerous fcn. */
- X break;
- X }
- X}
- X
- X
- X/* Is "opt" a valid input/output type? Set the flag too. */
- X
- XBOOL CheckIOType(char opt, int ioFlag, FLAGS theFlags[])
- X{
- X return(IsIOType(theFlags[ioFlag] = opt));
- X}
- X
- X
- X/* Is "ioType" a valid input/output type? */
- X
- XBOOL IsIOType(char ioType)
- X{
- X return( (ioType == OPT_TEXT)
- X || (ioType == OPT_BINARY)
- X || (ioType == OPT_MIDI));
- X}
- X
- X
- X/* Did user specify both input and output types? */
- X
- XBOOL CheckFlags(FLAGS theFlags[])
- X{
- X return(theFlags[FLAG_ITYPE] && theFlags[FLAG_OTYPE]);
- X}
- X
- X
- X/************************************************************************
- X* ^C handling -- Manx stuff.
- X************************************************************************/
- X
- Xvoid _abort(void)
- X{
- X SerialShutdown();
- X exit(RETURN_FAIL);
- X}
- END_OF_FILE
- if test 4433 -ne `wc -c <'Source/main.c'`; then
- echo shar: \"'Source/main.c'\" unpacked with wrong size!
- fi
- # end of 'Source/main.c'
- fi
- if test -f 'Source/midi.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Source/midi.h'\"
- else
- echo shar: Extracting \"'Source/midi.h'\" \(1182 characters\)
- sed "s/^X//" >'Source/midi.h' <<'END_OF_FILE'
- X#ifndef _MIDI_H
- X#define _MIDI_H 1
- X
- X/***************************************************************************
- X * MIDI values that are independent of any particular synthesizer.
- X ***************************************************************************/
- X
- X/***************************************************************************
- X * Some system-exclusive message constants.
- X ***************************************************************************/
- X
- X#define SYSEX_BEGIN 0xF0
- X#define SYSEX_END 0xF7
- X
- X/***************************************************************************
- X * Allow use of MIDI interfaces not attached to the internal serial port,
- X * unit 0. Here are the defaults.
- X ***************************************************************************/
- X
- X#define DEFAULT_MIDI_DEVICE "serial.device"
- X#define DEFAULT_MIDI_UNIT 0
- X#define MIDI_ENV_VAR "MP_MIDI_DEVICE"
- X
- X#define MIDI_BAUD_RATE 31250
- X
- X#ifndef CTRL_C_NO_BYTES
- X#define CTRL_C_NO_BYTES (-1)
- X#endif
- X
- X/***************************************************************************
- X * End of this header file.
- X ***************************************************************************/
- X
- X#endif /* _MIDI_H */
- END_OF_FILE
- if test 1182 -ne `wc -c <'Source/midi.h'`; then
- echo shar: \"'Source/midi.h'\" unpacked with wrong size!
- fi
- # end of 'Source/midi.h'
- fi
- if test -f 'Source/mp.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Source/mp.h'\"
- else
- echo shar: Extracting \"'Source/mp.h'\" \(8727 characters\)
- sed "s/^X//" >'Source/mp.h' <<'END_OF_FILE'
- X/**************************************************************************
- X* mp.h: Main header file.
- X* Part of MP, the MIDI Playground.
- X*
- X* Author: Daniel Barrett
- X* Version: See the file "version.h".
- X* Copyright: None! This program is in the Public Domain.
- X* Please share it with others.
- X***************************************************************************/
- X
- X
- X#ifndef _MP_H
- X
- X#include <devices/serial.h>
- X#include <exec/devices.h>
- X#include <exec/memory.h>
- X#include <exec/ports.h>
- X#include <exec/types.h>
- X#include <exec/interrupts.h>
- X#include <libraries/dos.h>
- X#include <libraries/dosextens.h>
- X#include <workbench/startup.h>
- X#include <workbench/workbench.h>
- X#include <functions.h>
- X#include <stdio.h>
- X
- X#ifndef __C_MACROS__
- X#define __C_MACROS__
- X#endif
- X#include <ctype.h>
- X
- X
- X/**************************************************************************
- X* Types.
- X**************************************************************************/
- X
- Xtypedef unsigned char STATE_T; /* An automaton state. */
- Xtypedef UBYTE MIDI_VALUE; /* A single MIDI data value. */
- Xtypedef signed char MIDI_RESULT; /* What happened while reading? */
- Xtypedef char FLAGS; /* Internal flags. */
- X
- X/**************************************************************************
- X* Return values from our input routine.
- X**************************************************************************/
- X
- X#define RESULT_OK (MIDI_RESULT)(1) /* Legal value read. */
- X#define RESULT_ERROR (MIDI_RESULT)(2) /* Illegal value read. */
- X#define RESULT_OVERFLOW (MIDI_RESULT)(3) /* Value overflowed. */
- X#define RESULT_STOP (MIDI_RESULT)(4) /* End of data. */
- X
- X/**************************************************************************
- X* States of our finite automaton for reading input.
- X**************************************************************************/
- X
- X#define STATE_SUCCESS 1 /* Got a legal value. */
- X#define STATE_ERROR 2 /* Had an input error. */
- X#define STATE_OVERFLOW 3 /* Read too big a value. */
- X#define STATE_NORMAL 4 /* Haven't read anything yet. */
- X#define STATE_INCOMMENT 5 /* Skipping a comment. */
- X#define STATE_INDECIMAL 6 /* Reading a base 10 number. */
- X#define STATE_LEADZERO 7 /* Read a leading zero. */
- X#define STATE_INOCTAL 8 /* Reading an octal number. */
- X#define STATE_STARTHEX 9 /* Read 1st digit of hex number. */
- X#define STATE_INHEX 10 /* Reading a hex number. */
- X#define STATE_STARTBINARY 11 /* Read 1st symbol of binary num. */
- X#define STATE_INBINARY 12 /* Reading a binary number. */
- X#define STATE_NEGATIVE 13 /* UNUSED. FOR FUTURE UPDATE. */
- X#define STATE_INCHAR 14 /* Reading a char constant. */
- X#define STATE_EXPECTQUOTE 15 /* Finishing a char constant. */
- X#define STATE_BACKSLASHINCHAR 16 /* Backslash in a char constant. */
- X#define STATE_BACKSLASHINSTRING 17 /* Backslash in a string constant. */
- X#define STATE_INCLUDEFILE 18 /* UNUSED. FOR FUTURE UPDATE. */
- X
- X
- X/**************************************************************************
- X* Macros for converting characters to numbers:
- X*
- X* D_TO_INT(c) Convert a digit to its numeric value.
- X* L_TO_INT(c) Convert a letter (A..F) to its base 16 value.
- X* H_TO_INT(c) Convert a hex digit to its numeric value.
- X**************************************************************************/
- X
- X#define D_TO_INT(c) ((long)((c) - '0'))
- X#define L_TO_INT(c) ((long)((toupper(c)) - 'A') + 10)
- X#define H_TO_INT(c) (isdigit(c) ? D_TO_INT(c) : L_TO_INT(c))
- X
- X/**************************************************************************
- X* Macros for classifying types of input. The rest are in <ctype.h>.
- X**************************************************************************/
- X
- X#define isoctal(c) (((c) >= '0') && ((c) <= '7'))
- X
- X/**************************************************************************
- X* Other macros.
- X**************************************************************************/
- X
- X#define MAX(a,b) (((a) > (b)) ? (a) : (b))
- X#define MIN(a,b) (((a) < (b)) ? (a) : (b))
- X
- X#define OpenReadFile(filename) OpenAFile(filename, "r", "read")
- X#define OpenWriteFile(filename) OpenAFile(filename, "w", "write")
- X
- X
- X/**************************************************************************
- X* The largest legal value our input routine can handle.
- X**************************************************************************/
- X
- X#define LARGEST_VALUE (MIDI_VALUE)(255)
- X#define BITS_IN_MIDI_VALUE BITSPERBYTE /* in types.h */
- X
- X/***************************************************************************
- X* Character constants for classifying the input.
- X***************************************************************************/
- X
- X#define START_BINARY '#' /* Symbol for start of binary number. */
- X#define HELP_SYMBOL '?' /* Symbol for help request from user. */
- X#define START_COMMENT ';' /* Start-comment symbol. */
- X
- X/***************************************************************************
- X* Command-line Options.
- X***************************************************************************/
- X
- X#define OPT_INPUT 'i' /* Input format. */
- X#define OPT_OUTPUT 'o' /* Output format. */
- X#define OPT_TEXT 't' /* Text I/O. */
- X#define OPT_BINARY 'b' /* Binary I/O. */
- X#define OPT_MIDI 'm' /* MIDI I/O. */
- X#define OPT_SYSEX 'x' /* UNUSED. FOR FUTURE UPDATE. */
- X#define OPT_INFILE 'g' /* Get from file. */
- X#define OPT_OUTFILE 'p' /* Put to file. */
- X
- X/* For getopt(). */
- X#define GETOPT_OPTIONS "i:o:g:p:x";
- Xextern int optind;
- Xextern char *optarg;
- X
- X/***************************************************************************
- X* Flags, and their associated macros.
- X***************************************************************************/
- X
- X#define NUM_FLAGS 3 /* How many flags? */
- X
- X#define FLAG_ITYPE 0 /* Flag ID's. */
- X#define FLAG_OTYPE 1
- X#define FLAG_SYSEX 2
- X
- X
- X/***************************************************************************
- X* Prototypes.
- X***************************************************************************/
- X
- X/* read.c */
- XSTATE_T NewState(int c, STATE_T state, MIDI_VALUE *answer);
- XSTATE_T NonStringState(int c, STATE_T state, MIDI_VALUE *answer);
- XSTATE_T DoNormal(int c, MIDI_VALUE *answer);
- XSTATE_T DoDecimal(int c, MIDI_VALUE *answer);
- XSTATE_T DoOctal(int c, MIDI_VALUE *answer);
- XSTATE_T DoHex(int c, MIDI_VALUE *answer);
- XSTATE_T DoInHex(int c, MIDI_VALUE *answer);
- XSTATE_T DoBinary(int c, MIDI_VALUE *answer);
- XSTATE_T DoInBinary(int c, MIDI_VALUE *answer);
- XSTATE_T DoLeadZero(int c, MIDI_VALUE *answer);
- XSTATE_T IncreaseIfPossible(MIDI_VALUE *answer, int newNum, int base,
- X STATE_T newState);
- XSTATE_T DoInChar(int c, MIDI_VALUE *answer);
- XSTATE_T DoExpectQuote(int c, MIDI_VALUE *answer);
- XSTATE_T DoBackslash(int c, MIDI_VALUE *answer, STATE_T newState);
- XSTATE_T DoInString(int c, STATE_T state, MIDI_VALUE *answer,
- X short *inString);
- XSTATE_T DoComment(int c);
- Xvoid InputHelp();
- X
- Xvoid PrintNumber(MIDI_VALUE number, FILE *out);
- Xvoid PrintBinary(MIDI_VALUE number, FILE *out);
- X
- X/* serial.c */
- Xshort SerialSetup(FLAGS sysex);
- Xvoid SerialShutdown(void);
- Xvoid ResetSerialPort(void);
- Xlong AnyMidiData(void);
- Xvoid PrepareToReadMidi(UBYTE *buf, int len);
- Xvoid PrepareToWriteMidi(UBYTE *buf, int len);
- Xlong DoTheIO(void);
- Xlong FastSerialRead(UBYTE buf[]);
- X
- X/* iofunctions.c */
- XMIDI_RESULT FromMidi(FILE *in, MIDI_VALUE *value);
- XBOOL ToMidi(FILE *in, MIDI_VALUE value);
- XMIDI_RESULT FromText(FILE *in, MIDI_VALUE *value);
- XBOOL ToText(FILE *in, MIDI_VALUE value);
- XMIDI_RESULT FromBinary(FILE *in, MIDI_VALUE *value);
- XBOOL ToBinary(FILE *in, MIDI_VALUE value);
- Xvoid SkipText(FILE *in, MIDI_VALUE value);
- Xvoid SkipMidi(FILE *in, MIDI_VALUE junk);
- Xvoid SkipBinary(FILE *in, MIDI_VALUE junk);
- X
- X/* main.c */
- XBOOL IsIOType(char ioType);
- XBOOL CheckIOType(char opt, int ioFlag, FLAGS theFlags[]);
- XBOOL HandleOptions(int argc, char *argv[], FLAGS theFlags[],
- X char **infile, char **outfile);
- Xvoid ReadAndWriteStuff(FLAGS theFlags[], FILE *in, FILE *out);
- Xvoid SetTheFunctions(MIDI_RESULT (**getfcn)(), BOOL (**putfcn)(),
- X void (**skipfcn)(), FLAGS theFlags[]);
- XBOOL CheckFlags(FLAGS theFlags[]);
- Xvoid InitStuff(FLAGS theFlags[], FILE **in, FILE **out, char **inFile,
- X char **outFile);
- XBOOL MIDIPlayground(FLAGS theFlags[], FILE *in, FILE *out);
- X
- X/* wb.c */
- X
- X/* help.c */
- Xvoid BegForUsage(char *progName);
- Xvoid Help(char *progName);
- X
- X/* files.c */
- XFILE *OpenAFile(char *filename, char *mode, char *readOrWrite);
- XBOOL FileExists(char *filename);
- XBOOL DontOverwriteExistingFile(char *filename);
- XBOOL SetupFiles(char *infile, char *outfile, FILE **in, FILE **out);
- Xvoid CloseFiles(FILE *in, FILE *out, char *filein, char *fileout);
- XBOOL MakeFilename(char **dest, char *src);
- X
- X#ifndef OpenReadFile
- XFILE *OpenReadFile(char *filename);
- X#endif
- X
- X#ifndef OpenWriteFile
- XFILE *OpenWriteFile(char *filename);
- X#endif
- X
- X
- X#endif /* _MP_H */
- END_OF_FILE
- if test 8727 -ne `wc -c <'Source/mp.h'`; then
- echo shar: \"'Source/mp.h'\" unpacked with wrong size!
- fi
- # end of 'Source/mp.h'
- fi
- if test -f 'Source/serial.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Source/serial.c'\"
- else
- echo shar: Extracting \"'Source/serial.c'\" \(7123 characters\)
- sed "s/^X//" >'Source/serial.c' <<'END_OF_FILE'
- X/**************************************************************************
- X* serial.c: Serial port access functions.
- X* Part of MP, the MIDI Playground.
- X*
- X* Author: Daniel Barrett
- X* Version: See the file "version.h".
- X* Copyright: None! This program is in the Public Domain.
- X* Please share it with others.
- X***************************************************************************/
- X
- X
- X#include "mp.h"
- X#include "midi.h"
- X
- Xstatic struct MsgPort *MidiPort = NULL;
- Xstatic struct IOExtSer *Midi = NULL;
- Xlong serialFlags = 0L;
- X
- X#define F_MIDIPORT 1
- X#define F_MIDI 2
- X#define F_DEVICE 4
- X#define F_SERPARAMS 8
- X
- X
- XBOOL AllDigits(char *str);
- Xchar *GetEnv(char *str);
- XBOOL MakeSerialDeviceName(char *str, char *device, int *unit);
- X
- X
- X/****************************************************************************
- X * SerialSetup: Open the serial port and its message port.
- X * Allow for an alternate MIDI device in an environment variable.
- X ***************************************************************************/
- X
- XBOOL SerialSetup(FLAGS sysex)
- X{
- X char deviceName[BUFSIZ], *envVar;
- X int unit;
- X
- X /* Set the defaults. */
- X
- X strcpy(deviceName, DEFAULT_MIDI_DEVICE);
- X unit = DEFAULT_MIDI_UNIT;
- X
- X /* If environment variable is set, find the real MIDI device info. */
- X
- X if ((envVar = GetEnv(MIDI_ENV_VAR))
- X && (!MakeSerialDeviceName(envVar, deviceName, &unit)))
- X return(FALSE);
- X
- X /* Create a port. */
- X
- X if (! (MidiPort = CreatePort(0, 0)) )
- X {
- X fprintf(stderr, "Cannot create port\n");
- X SerialShutdown();
- X return(FALSE);
- X }
- X else
- X serialFlags |= F_MIDIPORT;
- X
- X /* Create an extended I/O structure. */
- X
- X if (! (Midi = (struct IOExtSer *)
- X CreateExtIO(MidiPort, sizeof(struct IOExtSer))))
- X {
- X fprintf(stderr, "Cannot create extended I/O structure\n");
- X SerialShutdown();
- X return(FALSE);
- X }
- X else
- X serialFlags |= F_MIDI;
- X
- X /* Open the serial device. */
- X
- X Midi->io_SerFlags = SERF_SHARED;
- X if (OpenDevice(deviceName, unit, (struct IORequest *)Midi, 0))
- X {
- X fprintf(stderr,
- X "Cannot open serial device \"%s\", unit %d.\n",
- X deviceName, unit);
- X SerialShutdown();
- X return(FALSE);
- X }
- X else
- X serialFlags |= F_DEVICE;
- X
- X /* Set the serial device parameters. */
- X
- X Midi->io_SerFlags = SERF_RAD_BOOGIE;
- X if (sysex)
- X {
- X Midi->io_TermArray.TermArray0 = 0xF7F7F7F7;
- X Midi->io_TermArray.TermArray1 = 0xF7F7F7F7;
- X Midi->io_SerFlags |= SERF_EOFMODE;
- X }
- X Midi->io_Baud = MIDI_BAUD_RATE;
- X Midi->io_ExtFlags = 0; /* For future compatibility */
- X Midi->IOSer.io_Command = SDCMD_SETPARAMS;
- X
- X if (DoIO((struct IORequest *)Midi) != 0)
- X {
- X fprintf(stderr, "Cannot set serial parameters.\n");
- X SerialShutdown();
- X return(FALSE);
- X }
- X else
- X serialFlags |= F_SERPARAMS;
- X
- X return(TRUE);
- X}
- X
- X
- X/****************************************************************************
- X * SerialShutdown: Close the serial port and its message port.
- X ***************************************************************************/
- X
- Xvoid SerialShutdown(void)
- X{
- X if (serialFlags & F_DEVICE)
- X {
- X ResetSerialPort();
- X AbortIO((struct IORequest *)Midi);
- X WaitIO((struct IORequest *)Midi);
- X CloseDevice((struct IORequest *)Midi);
- X }
- X
- X if (serialFlags & F_MIDI)
- X DeleteExtIO((struct IORequest *)Midi);
- X
- X if (serialFlags & F_MIDIPORT)
- X DeletePort(MidiPort);
- X}
- X
- X/****************************************************************************
- X * ResetSerialPort: Clear all data from the serial port.
- X ***************************************************************************/
- X
- Xvoid ResetSerialPort(void)
- X{
- X Midi->IOSer.io_Command = CMD_CLEAR;
- X DoIO((struct IORequest *)Midi);
- X}
- X
- X
- X/****************************************************************************
- X * Is any data there?
- X ***************************************************************************/
- X
- Xlong AnyMidiData(void)
- X{
- X Midi->IOSer.io_Command = SDCMD_QUERY;
- X DoIO((struct IORequest *)Midi);
- X return(Midi->IOSer.io_Actual);
- X}
- X
- X
- X/****************************************************************************
- X * PrepareToReadMidi: Prepare a READ request for the MIDI port.
- X * PrepareToWriteMidi: Prepare a WRITE request for the MIDI port.
- X ***************************************************************************/
- X
- Xvoid PrepareToReadMidi(UBYTE buf[], int len)
- X{
- X Midi->IOSer.io_Command = CMD_READ;
- X Midi->IOSer.io_Data = (APTR)buf;
- X Midi->IOSer.io_Length = len;
- X}
- X
- X
- Xvoid PrepareToWriteMidi(UBYTE buf[], int len)
- X{
- X Midi->IOSer.io_Command = CMD_WRITE;
- X Midi->IOSer.io_Data = (APTR)buf;
- X Midi->IOSer.io_Length = len;
- X}
- X
- X
- X/****************************************************************************
- X* DoTheIO: General-purpose MIDI I/O routine. Quits on ^C.
- X****************************************************************************/
- X
- Xlong DoTheIO(void)
- X{
- X int mask, temp;
- X long bytesDone = 0L;
- X
- X mask = SIGBREAKF_CTRL_C | (1L << MidiPort->mp_SigBit);
- X SendIO((struct IORequest *)Midi);
- X
- X while (1)
- X {
- X temp = Wait(mask);
- X if (temp & SIGBREAKF_CTRL_C)
- X {
- X bytesDone = CTRL_C_NO_BYTES;
- X break;
- X }
- X
- X if (CheckIO((struct IORequest *)Midi))
- X {
- X WaitIO((struct IORequest *)Midi);
- X bytesDone = Midi->IOSer.io_Actual;
- X break;
- X }
- X }
- X
- X AbortIO((struct IORequest *)Midi);
- X WaitIO((struct IORequest *)Midi);
- X return(bytesDone);
- X}
- X
- X
- X/****************************************************************************
- X* Fast serial reading routine, from idea on 1.3 RKM's page 863.
- X* If any data is waiting, get all of it with DoIO(). Otherwise, post an
- X* asynchronous request for 1 byte. Repeat this in the calling program.
- X****************************************************************************/
- X
- Xlong FastSerialRead(UBYTE buf[])
- X{
- X long bytesWaiting, bytesRead;
- X
- X if ((bytesWaiting = AnyMidiData()) > 0)
- X {
- X PrepareToReadMidi(buf, MIN(bytesWaiting, BUFSIZ));
- X DoIO((struct IORequest *)Midi);
- X return(Midi->IOSer.io_Actual);
- X }
- X else
- X {
- X PrepareToReadMidi(buf, 1);
- X return(DoTheIO());
- X }
- X}
- X
- X
- X/****************************************************************************
- X* Allow the use of another MIDI device than serial.device.
- X* Environment variable syntax is "DEVICENAME:UNITNUMBER".
- X* For example: "midi.device:2".
- X*
- X* "device" MUST be preallocated.
- X****************************************************************************/
- X
- XBOOL MakeSerialDeviceName(char *str, char *device, int *unit)
- X{
- X while (str && *str && (*str != ':'))
- X *(device++) = *(str++);
- X
- X *device = '\0';
- X
- X if ((*str != ':') || *(str+1) == '\0')
- X {
- X fprintf(stderr,
- X "Your MIDI device name (variable "
- X MIDI_ENV_VAR
- X ") is missing a colon\nand/or a unit number.\n");
- X return(FALSE);
- X }
- X str++;
- X
- X if (!AllDigits(str))
- X {
- X fprintf(stderr,
- X "Your MIDI device unit number (variable "
- X MIDI_ENV_VAR
- X ") must be\na positive integer.\n");
- X return(FALSE);
- X }
- X else
- X *unit = atoi(str);
- X
- X return(TRUE);
- X}
- X
- X
- X/* AllDigits: Return TRUE iff the string "str" consists only of digits. */
- X
- XBOOL AllDigits(char *str)
- X{
- X if ((!str) || (*str == '\0')) /* NULL or empty string. */
- X return(FALSE);
- X else
- X while (*str) /* For each character... */
- X if (!isdigit(*str)) /* if not a digit... */
- X return(FALSE); /* goodbye! */
- X else
- X str++;
- X return(TRUE); /* All were digits. */
- X}
- END_OF_FILE
- if test 7123 -ne `wc -c <'Source/serial.c'`; then
- echo shar: \"'Source/serial.c'\" unpacked with wrong size!
- fi
- # end of 'Source/serial.c'
- fi
- if test -f 'Source/text.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Source/text.c'\"
- else
- echo shar: Extracting \"'Source/text.c'\" \(9628 characters\)
- sed "s/^X//" >'Source/text.c' <<'END_OF_FILE'
- X/**************************************************************************
- X* text.c: Functions for text input/output.
- X* Part of MP, the MIDI Playground.
- X*
- X* Author: Daniel Barrett
- X* Version: See the file "version.h".
- X* Copyright: None! This program is in the Public Domain.
- X* Please share it with others.
- X***************************************************************************/
- X
- X
- X#include "mp.h"
- X
- X
- X/* Given the currently read character and the current state, compute
- X * the new state and the MIDI value. */
- X
- XSTATE_T NewState(int c, STATE_T state, MIDI_VALUE *answer)
- X{
- X static BOOL inString = FALSE;
- X
- X if (inString)
- X return(DoInString(c, state, answer, &inString));
- X else if (c == HELP_SYMBOL)
- X {
- X InputHelp();
- X return(state);
- X }
- X else if (state == STATE_NORMAL && c == '\"')
- X {
- X inString = TRUE;
- X return(STATE_NORMAL); /* Doesn't matter. */
- X }
- X else
- X return(NonStringState(c, state, answer));
- X}
- X
- X/****************************************************************************
- X* Our finite automaton for non-strings. Process the character and return
- X* the new state.
- X****************************************************************************/
- X
- XSTATE_T NonStringState(int c, STATE_T state, MIDI_VALUE *answer)
- X{
- X switch (state)
- X {
- X case STATE_NORMAL: return(DoNormal(c, answer));
- X case STATE_INCOMMENT: return(DoComment(c));
- X case STATE_INDECIMAL: return(DoDecimal(c, answer));
- X case STATE_INOCTAL: return(DoOctal(c, answer));
- X case STATE_STARTHEX: return(DoHex(c, answer));
- X case STATE_INHEX: return(DoInHex(c, answer));
- X case STATE_LEADZERO: return(DoLeadZero(c, answer));
- X case STATE_INCHAR: return(DoInChar(c, answer));
- X case STATE_STARTBINARY: return(DoBinary(c, answer));
- X case STATE_INBINARY: return(DoInBinary(c, answer));
- X case STATE_EXPECTQUOTE: return(DoExpectQuote(c, answer));
- X case STATE_BACKSLASHINCHAR:
- X return(DoBackslash(c, answer, STATE_EXPECTQUOTE));
- X case STATE_SUCCESS:
- X case STATE_OVERFLOW:
- X case STATE_ERROR: return(state);
- X }
- X}
- X
- X
- X/****************************************************************************
- X* We are not currently in a number. A character is read; decide what to
- X* do with it.
- X****************************************************************************/
- X
- XSTATE_T DoNormal(int c, MIDI_VALUE *answer)
- X{
- X if (isspace(c))
- X return(STATE_NORMAL);
- X else if (c == START_COMMENT)
- X return(STATE_INCOMMENT);
- X else if (c == START_BINARY)
- X return(STATE_STARTBINARY);
- X else if (c == '\'')
- X return(STATE_INCHAR);
- X else if (c == '0')
- X return(STATE_LEADZERO);
- X else if (toupper(c) == 'H')
- X return(STATE_STARTHEX);
- X else if (isdigit(c))
- X {
- X *answer = D_TO_INT(c);
- X return(STATE_INDECIMAL);
- X }
- X else if (isxdigit(c))
- X {
- X *answer = H_TO_INT(c);
- X return(STATE_INHEX);
- X }
- X else
- X return(STATE_ERROR);
- X}
- X
- X
- X/****************************************************************************
- X* Base 10 (decimal) numbers.
- X****************************************************************************/
- X
- XSTATE_T DoDecimal(int c, MIDI_VALUE *answer)
- X{
- X if (isdigit(c))
- X return(IncreaseIfPossible(answer, D_TO_INT(c), 10,
- X STATE_INDECIMAL));
- X else if (isspace(c))
- X return(STATE_SUCCESS);
- X else
- X return(STATE_ERROR);
- X}
- X
- X
- X/****************************************************************************
- X* Octal numbers.
- X****************************************************************************/
- X
- XSTATE_T DoOctal(int c, MIDI_VALUE *answer)
- X{
- X if (isoctal(c))
- X return(IncreaseIfPossible(answer, D_TO_INT(c), 8,
- X STATE_INOCTAL));
- X else if (isspace(c))
- X return(STATE_SUCCESS);
- X else
- X return(STATE_ERROR);
- X}
- X
- X
- X/****************************************************************************
- X* Hexadecimal numbers.
- X****************************************************************************/
- X
- XSTATE_T DoHex(int c, MIDI_VALUE *answer)
- X{
- X if (isxdigit(c))
- X {
- X *answer = H_TO_INT(c);
- X return(STATE_INHEX);
- X }
- X else
- X return(STATE_ERROR);
- X}
- X
- X
- XSTATE_T DoInHex(int c, MIDI_VALUE *answer)
- X{
- X if (isxdigit(c))
- X return(IncreaseIfPossible(answer, H_TO_INT(c), 16,
- X STATE_INHEX));
- X else if (isspace(c))
- X return(STATE_SUCCESS);
- X else
- X return(STATE_ERROR);
- X}
- X
- X
- X/****************************************************************************
- X* Binary numbers.
- X****************************************************************************/
- X
- XSTATE_T DoBinary(int c, MIDI_VALUE *answer)
- X{
- X if ((c == '0') || (c == '1'))
- X {
- X *answer = D_TO_INT(c);
- X return(STATE_INBINARY);
- X }
- X else
- X return(STATE_ERROR);
- X}
- X
- X
- XSTATE_T DoInBinary(int c, MIDI_VALUE *answer)
- X{
- X if ((c == '0') || (c == '1'))
- X return(IncreaseIfPossible(answer, D_TO_INT(c), 2,
- X STATE_INBINARY));
- X else if (isspace(c))
- X return(STATE_SUCCESS);
- X else
- X return(STATE_ERROR);
- X}
- X
- X
- X/****************************************************************************
- X* Hook for negative numbers. Commented out right now.
- X****************************************************************************/
- X
- X#ifdef ALLOW_NEGATIVE
- XSTATE_T DoNegative(int c, MIDI_VALUE *answer)
- X{
- X if (c == '0')
- X return(STATE_LEADZERO);
- X else if (isdigit(c))
- X {
- X return(STATE_INDECIMAL);
- X }
- X else
- X return(STATE_ERROR);
- X}
- X#endif /* ALLOW_NEGATIVE */
- X
- X
- X/****************************************************************************
- X* Leading zero was found: Do octal or hexadecimal as required.
- X****************************************************************************/
- X
- XSTATE_T DoLeadZero(int c, MIDI_VALUE *answer)
- X{
- X if (toupper(c) == 'X')
- X return(STATE_STARTHEX);
- X else if (isoctal(c))
- X {
- X *answer = D_TO_INT(c);
- X return(STATE_INOCTAL);
- X }
- X else if (isspace(c))
- X return(STATE_SUCCESS);
- X else
- X return(STATE_ERROR);
- X}
- X
- X
- X/****************************************************************************
- X* Append the digit "newNum" onto the right of the number *answer.
- X* Don't allow overflow. Works for any base. Return newState on success.
- X****************************************************************************/
- X
- XSTATE_T IncreaseIfPossible(MIDI_VALUE *answer, int newNum, int base,
- X STATE_T newState)
- X{
- X if ((*answer) > (LARGEST_VALUE / base))
- X return(STATE_OVERFLOW);
- X else
- X {
- X *answer *= base;
- X
- X if ((*answer) > (LARGEST_VALUE - newNum))
- X return(STATE_OVERFLOW);
- X else
- X {
- X *answer += newNum;
- X return(newState);
- X }
- X }
- X}
- X
- X
- X/****************************************************************************
- X* Character-oriented routines.
- X****************************************************************************/
- X
- XSTATE_T DoInChar(int c, MIDI_VALUE *answer)
- X{
- X if (c == '\\')
- X return(STATE_BACKSLASHINCHAR);
- X else
- X {
- X *answer = c;
- X return(STATE_EXPECTQUOTE);
- X }
- X}
- X
- X
- XSTATE_T DoExpectQuote(int c, MIDI_VALUE *answer)
- X{
- X return((c == '\'') ? STATE_SUCCESS : STATE_ERROR);
- X}
- X
- X
- XSTATE_T DoBackslash(int c, MIDI_VALUE *answer, STATE_T newState)
- X{
- X switch (c)
- X {
- X case '0': *answer = '\0'; break;
- X case 'a': *answer = '\a'; break;
- X case 'b': *answer = '\b'; break;
- X case 'f': *answer = '\f'; break;
- X case 'n': *answer = '\n'; break;
- X case 'r': *answer = '\r'; break;
- X case 't': *answer = '\t'; break;
- X case 'v': *answer = '\v'; break;
- X case '\\':
- X case '\'':
- X case '\"': *answer = c; break;
- X default: return(STATE_ERROR);
- X }
- X return(newState);
- X}
- X
- X
- X/****************************************************************************
- X* String-oriented routines.
- X****************************************************************************/
- X
- XSTATE_T DoInString(int c, STATE_T state, MIDI_VALUE *answer, BOOL *inString)
- X{
- X switch (state)
- X {
- X case STATE_NORMAL:
- X if (c == '\"')
- X {
- X *inString = FALSE;
- X return(STATE_NORMAL);
- X }
- X else if (c == '\\')
- X return(STATE_BACKSLASHINSTRING);
- X else
- X {
- X *answer = isspace(c) ? ' ' : c;
- X return(STATE_SUCCESS);
- X }
- X break;
- X case STATE_BACKSLASHINSTRING:
- X return(DoBackslash(c, answer, STATE_SUCCESS));
- X }
- X}
- X
- X
- X/****************************************************************************
- X* Handling comments. Everything from comment symbol to the end of the
- X* line is a comment.
- X****************************************************************************/
- X
- XSTATE_T DoComment(int c)
- X{
- X return( (c == '\n') ? STATE_NORMAL : STATE_INCOMMENT );
- X}
- X
- X/****************************************************************************
- X* Getting help.
- X****************************************************************************/
- X
- X
- Xvoid InputHelp()
- X{
- X fprintf(stderr, "INPUT\tMEANING\n"
- X "1-9...\tDecimal number.\n"
- X "0...\tOctal number.\n"
- X "0x...\tHexadecimal number (case-insensitive).\n"
- X "H...\tHexadecimal number (case-insensitive).\n"
- X "A-F...\tHexadecimal number (case-insensitive).\n"
- X "#...\tBinary number.\n"
- X "'x'\tThe character 'x'."
- X " C character syntax like \\n and \\t is valid.\n"
- X "\"...\"\tA text string."
- X " (Newlines turn into space characters.)\n"
- X "Largest legal input value is %ld (base 10).\n"
- X "All values must be separated by whitespace.\n\n",
- X LARGEST_VALUE);
- X}
- X
- X
- X/****************************************************************************
- X* Text output functions.
- X****************************************************************************/
- X
- Xvoid PrintNumber(MIDI_VALUE number, FILE *out)
- X{
- X fprintf(out, "Dec %3ld, Oct %3lo, Hex %3lX",
- X number, number, number);
- X
- X PrintBinary(number, out);
- X
- X if (isprint((char)number))
- X fprintf(out, ", Char '%c'", number);
- X
- X putc('\n', out);
- X}
- X
- X
- Xvoid PrintBinary(MIDI_VALUE number, FILE *out)
- X{
- X char buf[BITS_IN_MIDI_VALUE + 1];
- X int i, on;
- X
- X for (i=0; i<BITS_IN_MIDI_VALUE; i++)
- X {
- X on = number & (1 << i);
- X buf[BITS_IN_MIDI_VALUE-i-1] = '0' + (char)(on && 1);
- X }
- X
- X buf[BITS_IN_MIDI_VALUE] = '\0';
- X fprintf(out, ", Bin %s", buf);
- X}
- END_OF_FILE
- if test 9628 -ne `wc -c <'Source/text.c'`; then
- echo shar: \"'Source/text.c'\" unpacked with wrong size!
- fi
- # end of 'Source/text.c'
- fi
- if test -f 'Source/version.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Source/version.h'\"
- else
- echo shar: Extracting \"'Source/version.h'\" \(628 characters\)
- sed "s/^X//" >'Source/version.h' <<'END_OF_FILE'
- X/**************************************************************************
- X* version.h: The version number.
- X* Part of MP, the MIDI Playground.
- X*
- X* Author: Daniel Barrett
- X* Version: See the file "version.h".
- X* Copyright: None! This program is in the Public Domain.
- X* Please share it with others.
- X***************************************************************************/
- X
- X
- X#ifndef _VERSION_H
- X
- X/**************************************************************************
- X* Program version number.
- X**************************************************************************/
- X
- X#define VERSION "1.0"
- X
- X#endif /* _VERSION_H */
- END_OF_FILE
- if test 628 -ne `wc -c <'Source/version.h'`; then
- echo shar: \"'Source/version.h'\" unpacked with wrong size!
- fi
- # end of 'Source/version.h'
- fi
- if test -f 'Source/wb.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Source/wb.c'\"
- else
- echo shar: Extracting \"'Source/wb.c'\" \(86 characters\)
- sed "s/^X//" >'Source/wb.c' <<'END_OF_FILE'
- XBOOL WorkbenchProgram(char *argv[])
- X{
- X /* For future expansion. */
- X
- X return(FALSE);
- X}
- END_OF_FILE
- if test 86 -ne `wc -c <'Source/wb.c'`; then
- echo shar: \"'Source/wb.c'\" unpacked with wrong size!
- fi
- # end of 'Source/wb.c'
- fi
- echo shar: End of archive 1 \(of 2\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 2 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked both archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
- Mail comments to the moderator at <amiga-request@uunet.uu.net>.
- Post requests for sources, and general discussion to comp.sys.amiga.misc.
-